﻿using System;
using ENode.Domain;
using Infrastructure;

namespace Domain.Accounts
{
    /// <summary>账号聚合根
    /// </summary>
    public class Account : AggregateRoot<string>
    {
        private string _name;
        private string _password;
        private LastSignInInfo _lastSignInInfo;
        private LastSignOutInfo _lastSignOutInfo;

        ///// <summary>
        ///// 累计在线时间
        ///// </summary>
        //private long TotalOnline;

        #region NewAccount


        public Account(string id, string name, string password)
            : base(id)
        {
            Assert.IsNotNullOrWhiteSpace("账号", name);
            Assert.IsNotNullOrWhiteSpace("密码", password);
            if (name.Length > 128)
            {
                throw new Exception("账号长度不能超过128");
            }
            if (password.Length > 128)
            {
                throw new Exception("密码长度不能超过128");
            }
            ApplyEvent(new NewAccountRegisteredEvent(this, name, password));
        }

        private void Handle(NewAccountRegisteredEvent evnt)
        {
            _id = evnt.AggregateRootId;
            _name = evnt.Name;
            _password = evnt.Password;
            _lastSignInInfo = new LastSignInInfo("", DateTime.Now, 0,"");
            _lastSignOutInfo = new LastSignOutInfo(DateTime.Now, 0,"");
        }

        #endregion


        #region SignIn

        public void SignIn(string ipAddress, string sessionId)
        {
            ApplyEvent(new SignInAfterEvent(this, new LastSignInInfo(
                ipAddress,
                DateTime.Now,
                this._lastSignInInfo.TotalTimes + 1,
                sessionId
            )));
        }

        /// <summary>
        /// 聚合根重建（事件追溯）时，会调用该方法。
        /// </summary>
        /// <param name="evnt"></param>
        private void Handle(SignInAfterEvent evnt)
        {
            this._lastSignInInfo = evnt.StatisticInfo;
        }
        #endregion


        #region SignOut

        public void SignOut(string sessionId)
        {
            ApplyEvent(new SignOutAfterEvent(this, new LastSignOutInfo(
                DateTime.Now,
                this._lastSignOutInfo.TotalTimes + 1,
                sessionId
            )));
        }
        private void Handle(SignOutAfterEvent evnt)
        {
            this._lastSignOutInfo = evnt.StatisticInfo;
        }
        #endregion
    }
}